package xin.mydreams.purple.config;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import xin.mydreams.purple.annotation.Autowired;
import xin.mydreams.purple.annotation.RequestMapping;
import xin.mydreams.purple.annotation.RestController;
import xin.mydreams.purple.annotation.Service;
import xin.mydreams.purple.constant.PurpleConstant;

public class PurpleSetting {

	private static Properties properties = new Properties();
	private static List<String> classNames = new ArrayList<>();
	private static Map<String, Object> ioc = new HashMap<>();
	private static Map<String, Method> methodMapping = new HashMap<>();
	private static Map<String, Object> classMap = new HashMap<>();

	/**
	 * 获取配置文件的配置项
	 *
	 * @date Created at 2018年12月7日 下午10:12:03
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 * @param key
	 * @return
	 */
	public static String getProperty(String key) {
		Object object = properties.get(key);
		if (object != null) {
			return String.valueOf(object);
		}
		return null;
	}

	public static List<String> getClassNames() {
		return classNames;
	}

	public static Map<String, Object> getIoc() {
		return ioc;
	}

	public static Map<String, Method> getMethodMapping() {
		return methodMapping;
	}

	public static Map<String, Object> getClassMap() {
		return classMap;
	}

	/**
	 * 初始化配置项
	 *
	 * @date Created at 2018年12月7日 下午9:18:59
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 * @param clazz
	 * @throws Exception
	 */
	public static void setting(Class<?> clazz) throws Exception {
		setting(clazz, null);
	}

	/**
	 * 初始化配置项
	 *
	 * @date Created at 2018年12月7日 下午9:19:15
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 * @param clazz
	 * @param propertiesName
	 * @throws Exception
	 */
	public static void setting(Class<?> clazz, String propertiesName) throws Exception {

		// 1.加载配置文件
		initConfiguration(clazz, propertiesName);
		// 2.初始化所有相关联的类,扫描用户设定的包下面所有的类
		doScanner(clazz, clazz.getPackage().getName());
		// 3.拿到扫描到的类,通过反射机制,实例化,并且放到ioc容器中(k-v beanName-bean) beanName默认是首字母小写
		doInstance();
		// 4.初始化AutoWired
		doAutoWired();
		// 5.初始化HandlerMapping(将url和method对应上)
		initHandlerMapping();
	}

	/**
	 * 读取配置文件
	 * 
	 * @throws Exception
	 */
	private static void initConfiguration(Class<?> clazz, String propertiesName) throws Exception {
		if (propertiesName == null) {
			propertiesName = PurpleConstant.SystemProperties.APPLICATION_PROPERTIES;
		}
		String url = clazz.getClassLoader().getResource(propertiesName).getPath();
		FileInputStream fileInputStream = new FileInputStream(url);
		properties = new Properties();
		properties.load(fileInputStream);
		fileInputStream.close();
	}

	/**
	 * 读取所有的包
	 *
	 * @date Created at 2018年12月7日 下午10:15:04
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 * @param clazz
	 * @param packageName
	 */
	private static void doScanner(Class<?> clazz, String packageName) {
		// 把所有的.替换成/
		URL url = clazz.getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
		File dir = new File(url.getFile());
		for (File file : dir.listFiles()) {
			if (file.isDirectory()) {
				// 递归读取包
				doScanner(clazz, packageName + "." + file.getName());
			} else {
				String className = packageName + "." + file.getName().replace(".class", "");
				classNames.add(className);
			}
		}
	}

	/**
	 * 查看需要序列化的事例
	 *
	 * @date Created at 2018年12月7日 下午10:15:22
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 */
	private static void doInstance() {
		if (classNames.isEmpty()) {
			return;
		}
		for (String className : classNames) {
			try {
				// 把类搞出来,反射来实例化(只有加@MyController需要实例化)
				Class<?> clazz = Class.forName(className);
				if (clazz.isAnnotationPresent(RestController.class)) {
					ioc.put(toLowerFirstWord(clazz.getSimpleName()), clazz.newInstance());
				} else if (clazz.isAnnotationPresent(Service.class)) {
					Service service = clazz.getAnnotation(Service.class);
					String beanName = service.value();
					if ("".equals(beanName)) {
						beanName = toLowerFirstWord(clazz.getSimpleName());
					}
					Object instance = clazz.newInstance();
					ioc.put(beanName, instance);
					Class<?>[] interfaces = clazz.getInterfaces();
					for (Class<?> i : interfaces) {
						ioc.put(i.getName(), instance);
					}
				} else {
					continue;
				}
			} catch (Exception e) {
				e.printStackTrace();
				continue;
			}
		}
	}

	/**
	 * 初始化ioc
	 *
	 * @date Created at 2018年12月7日 下午10:15:48
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 */
	private static void initHandlerMapping() {
		if (ioc.isEmpty()) {
			return;
		}
		try {
			for (Entry<String, Object> entry : ioc.entrySet()) {
				Object value = entry.getValue();
				Class<? extends Object> clazz = value.getClass();
				if (!clazz.isAnnotationPresent(RestController.class)) {
					continue;
				}
				// 拼url时,是controller头的url拼上方法上的url
				String baseUrl = "";
				if (clazz.isAnnotationPresent(RequestMapping.class)) {
					RequestMapping annotation = clazz.getAnnotation(RequestMapping.class);
					baseUrl = annotation.value();
				}
				Method[] methods = clazz.getMethods();
				for (Method method : methods) {
					if (!method.isAnnotationPresent(RequestMapping.class)) {
						continue;
					}
					RequestMapping annotation = method.getAnnotation(RequestMapping.class);
					String url = annotation.value();
					url = (baseUrl + "/" + url).replaceAll("/+", "/");
					System.out.println(url);
					methodMapping.put(url, method);
					classMap.put(url, value);
					System.out.println(url + "," + method);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * //依赖注入->给加了Autowired注解的字段赋值
	 *
	 * @date Created at 2019年3月16日 上午11:00:29
	 * @emain guzehao@mydreams.xin
	 * @blog https://www.mydreams.xin
	 * @author 谷泽昊
	 */
	private static void doAutoWired() {
		if (ioc.isEmpty())
			return;
		for (Map.Entry<String, Object> entry : ioc.entrySet()) {
			// 依赖注入->给加了XXAutowired注解的字段赋值
			Object value = entry.getValue();
			Field[] fields =value.getClass().getDeclaredFields();
			for (Field field : fields) {
				if (!field.isAnnotationPresent(Autowired.class)) {
					continue;
				}
				Autowired autowired = field.getAnnotation(Autowired.class);
				String beanName = autowired.value();
				if ("".equals(beanName)) {
					beanName = field.getType().getName();
				}
				field.setAccessible(true);
				try {
					System.out.println(field+"----"+entry.getValue()+"----"+ioc.get(beanName));
					field.set(entry.getValue(), ioc.get(beanName));
					
					 System.out.println("值："+field.getType()); 
				} catch (IllegalAccessException e) {
					e.printStackTrace();
					continue;
				}
			}
		}
	}

	/**
	 * 把字符串的首字母小写
	 * 
	 * @param name
	 * @return
	 */
	private static String toLowerFirstWord(String name) {
		char[] charArray = name.toCharArray();
		charArray[0] += 32;
		return String.valueOf(charArray);
	}
}
